/*
* $Id: unetmgm.c,v 1.40 2008/03/07 01:44:55 sunny Exp $
*/

/*******************************************************************************
       UBEC (Uniband Electronic Corp.)

       Project: U-NET01, Ubiquitous network platform

       File: unet.c

       Version: 0.3.0

       Usage: Unet api & unet sub function

       Platform: U-NET01 DK with Keil 8051 C compiler

       Reference:

               Silicon Laboratories: C8051F124, C8051F340

               UBEC: UZ2400, UZ2410

       Note :

               Copyright (C) 2007 Uniband Electronic Corporation, All rights reserved

********************************************************************************/

#include "unet.h"

#if 0 // DEBUG_MODE
	#undef  TRACE_TAG
	#define TRACE_TAG()
	#undef  TRACE_puts
	#define TRACE_puts              DBG_puts
	#undef  TRACE_printf
	#define TRACE_printf(P)         dbg_printf P
#endif

/*******************************************************************************

	Unet Network Management Sub Functions

********************************************************************************/

UINT8 RxUnetFrameParsing(UNET_HEADER* RxPtr)
{
	TRACE_puts("RxUnetFrameParsing");

	Endian_Modify(((UINT8*)RxPtr), 0xFF, RxPtr->UnetFrmType);
	switch(RxPtr->UnetFrmType){
		// 2007/8/8 13:45, Sunny: handle UNET_DATA in upper layer (unet_main.c).
		//	case UNET_DATA: //send to upper layer
		//		RxUnetData(RxPtr);
		//		break;
			case UNET_RESET:
				RxUnetReset();
				break;
			case UNET_LEAVE_CMD:
				RxUnetLeave(RxPtr);
				break;
			case UNET_KICK_CMD:
				RxUnetKick((UNET_KICK_FRAME* )RxPtr);
				break;
#ifdef I_Am_Coordinator
			case UNET_JOIN_REPORT:
				RxUnetJoinReport((UNET_JOINREPORT_FRAME* )RxPtr);
				break;
#endif
			case UNET_ASK_MAC_ADDR:
				TxUnetMARsp(RxPtr->SrcAddr);
				break;
#if 0
			case UNET_CS:
				RxUnetCleanSpace((UNET_LEAVE_FRAME* )RxPtr);
				break;
#endif
			case UNET_LL:
				break;
			case UNET_RSP_MAC_ADDR:
				RxUnetRspMA((UNET_RSP_MA_FRAME* )RxPtr);
				break;
#ifdef I_Am_Coordinator
			case UNET_LEAVE_REPORT:
				RxUnetLeaveReport((UNET_LEAVE_FRAME* )RxPtr);
				break;
#endif
			case UNET_QUERY_CMD:
				TxUnetRspQueryRelay();
				break;
			case UNET_QUERY_RELAY:
				RxUnetRspQueryRelay((UNET_QUERY_FRAME*)RxPtr);
				break;
			case UNET_RSP_QUERY:
				RxUnetRspQuery((UNET_QUERY_FRAME*)RxPtr);
				break;
#ifdef I_Am_Coordinator
			case UNET_MAC_ROUTE:
				RxUnetMACRouting((UNET_MAC_ROUTE_FRAME*)RxPtr);
				break;
#endif
			case UNET_LOCAL_QUERY:
				RxUnetLocalQuery((UNET_LOCAL_QUERY_FRAME*)RxPtr);
				break;
			case UNET_LOCAL_TALK:
				RxUnetLocalTalk((UNET_LOCAL_TALK_FRAME*)RxPtr);
				break;
			case UNET_REQ_TAB:
				RxUnetReqTable();
				break;
#ifdef I_Am_Coordinator
			case UNET_RSP_TAB:
				RxUnetRspTable((UNET_TAB_FRAME*)RxPtr);
				break;
#endif

#if DEBUG_FUNC
			case UNET_DBG_NODE_INFO_REQ:
				dbg_rx_node_info_req();
				break;
#ifdef I_Am_Coordinator
			case UNET_DBG_NODE_INFO_RSP:
				dbg_rx_node_info_rsp((UNET_NODE_INFO_FRAME*)RxPtr);
				break;
#endif
#endif
			default:
				break;

	}
	return SUCCESS;

}

UINT8 UNET_TX16(UINT16 DstAddr, UINT8 *DataPtr, UINT8 Length)
{
	UNET_HEADER* TxPtr;
//	UINT8 i;

#ifdef CHECKSUM
	UINT8 CSM;
#endif

	TRACE_puts("UNET_TX16");

	if(Length > UNET_MAX_TX16_DATA_PAYLOAD_LENGTH)
		return DATA_TOO_LONG;

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_DATA;
	TxPtr->DstAddr = DstAddr;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->MHR.DstAddr = 0xffff;
		TxPtr->MHR.Header.val = 0x8801;//broadcast without ACK

	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((TxPtr->MHR.DstAddr = unet_tree_routing(TxPtr->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

#ifdef DATAOUT
	RF_TX_BUFF[sizeof(UNET_HEADER)] = Length;
	MSG_Copy(&RF_TX_BUFF[sizeof(UNET_HEADER)+1], DataPtr, Length);
	TRACE_printf(("UNET_TX16: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER) + Length + 1, MT_DATA_IND, UNET_DATA);

#elif defined(CHECKSUM)
	CSM = UnetCheckSum(DataPtr, Length);

	RF_TX_BUFF[sizeof(UNET_HEADER)] = Length;
	RF_TX_BUFF[sizeof(UNET_HEADER)+1] = CSM;


	MSG_Copy(&RF_TX_BUFF[sizeof(UNET_HEADER)+2], DataPtr, Length);

	TRACE_printf(("UNET_TX16: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER) + Length + 2, MT_DATA_IND, UNET_DATA);

#else

	MSG_Copy(&RF_TX_BUFF[sizeof(UNET_HEADER)], DataPtr, Length);

	TRACE_printf(("UNET_TX16: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER) + Length, MT_DATA_IND, UNET_DATA);

#endif
}

#ifdef I_Am_Coordinator
UINT8 UNET_REMOTE_RESET(UINT16 DstAddr, UINT8 maxchild, UINT8 maxrouter, UINT8 maxdepth)
{
	UNET_RESET_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("UNET_REMOTE_RESET");

	TxPtr = (UNET_RESET_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_RESET_FRAME));

	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_RESET;
	TxPtr->UNETHeader.DstAddr = DstAddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	TxPtr->maxchild = maxchild;
	TxPtr->maxrouter = maxrouter;
	TxPtr->maxdepth = maxdepth;

	if(DstAddr == 0xffff){
		TxPtr->UNETHeader.MHR.DstAddr = 0xffff;
		TxPtr->UNETHeader.MHR.Header.val = 0x8801;
		UnetSys.Flag.NwkReset = 1;
		UnetSys.MaxChild = maxchild;
		UnetSys.MaxRouter = maxrouter;
		UnetSys.MaxDepth = maxdepth;
	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TRACE_printf(("UNET_REMOTE_RESET: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_RESET_FRAME), MT_DATA_IND, UNET_RESET);

}
#endif
UINT8 TxUnetJoinReport(UINT8* JoinChildMACAddr, UINT16 JoinChildNWKAddr)
{
	UNET_JOINREPORT_FRAME* TxPtr;
//	UINT8 i;
	UINT16 DstAddr = UNET_COORD_ADDRESS;

	TRACE_puts("TxUnetJoinReport");

	TxPtr = (UNET_JOINREPORT_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_JOINREPORT_FRAME));

	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_JOIN_REPORT;
	TxPtr->UNETHeader.DstAddr = DstAddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->UNETHeader.MHR.DstAddr = 0xffff;

	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TxPtr->JoinChildNWKAddress = JoinChildNWKAddr;

	MSG_Copy(TxPtr->JoinChildMACAddress, JoinChildMACAddr, 8);

	TRACE_printf(("TxUnetJoinReport: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_JOINREPORT_FRAME), MT_DATA_IND, UNET_JOIN_REPORT);

}

#ifdef I_Am_Coordinator
UINT8 UNET_KICK(UINT16 ParentAddr, UINT16 KickChildAddr, UINT16 NewParent)
{
	UNET_KICK_FRAME* TxPtr;
	struct _child_list_ *ChiPtr;
	struct _unet_children_table_ *ChiTabPtr;
//	UINT8 i;

	TRACE_puts("UNET_KICK");

	UnetSys.Flag.Kick = 1;

	TxPtr = (UNET_KICK_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_KICK_FRAME));

	//clean the children table
	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		ChiTabPtr = ChiTabPtr->Next;
		if(ChiTabPtr->NwkAddress == KickChildAddr) {
			clean_branch(KickChildAddr, ParentAddr);
			delete_node((void *)&UnetSys.ChildTableTail, (void *)&ChiTabPtr);
			break;
		}
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}
	UnetSys.Flag.Kick = 0;
	if(ParentAddr == UnetSys.NwkAddr){//Only Coordinator
		if((UnetSys.JoinRouterCnt + UnetSys.JoinEndevCnt) > 0){
			if((ChiPtr = UnetSys.ChildTail) != NULL) {
			    do {
				ChiPtr = ChiPtr->Next;
				if(ChiPtr->NetworkAddress == KickChildAddr) {
					unet_tx_disasso(ChiPtr->MacAddr, 0x1, NewParent);
					delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);

					RecycleAddress[RecycleIndex] = KickChildAddr;
					RecycleIndex+=1;

//					RecycleAddr = KickChildAddr;
					AddrRecycleFlg = 1;
					if(ChiPtr->Cap & 0x02)	// Router
						UnetSys.JoinRouterCnt--;
					else	// End device
						UnetSys.JoinEndevCnt--;

	//				clear_table((void *) &UnetSys.ChildHead);
	 				goto TX_UNET_KICK_LABEL;
				}
			    } while(ChiPtr != UnetSys.ChildTail);
			}
			return FAILURE;
		}

	}

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_KICK_CMD;
	TxPtr->UNETHeader.DstAddr = ParentAddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if(ParentAddr == 0xffff){
		TxPtr->UNETHeader.MHR.DstAddr = 0xffff;

	}else if(ParentAddr == UnetSys.NwkAddr){
		TxPtr->UNETHeader.MHR.DstAddr = KickChildAddr;
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TxPtr->KickChildAddress = KickChildAddr;
	TxPtr->NewParent = NewParent;

	TRACE_printf(("UNET_KICK: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	if(UzTx(RF_TX_BUFF, sizeof(UNET_KICK_FRAME), MT_DATA_IND, UNET_KICK_CMD)){
		//UNET_GET_TABLE();
		reset_timer(gettable_tm);
		return SUCCESS;
	}

TX_UNET_KICK_LABEL:
	reset_timer(gettable_tm);
	return SUCCESS;

}
#endif

UINT8 TxUnetLeaveReport(UINT16 LeaveChildAddr)
{
	UNET_LEAVE_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("TxUnetLeaveReport");

	TxPtr = (UNET_LEAVE_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_LEAVE_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_LEAVE_REPORT;
	TxPtr->UNETHeader.DstAddr = UNET_COORD_ADDRESS;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	TxPtr->LeaveChildAddress = LeaveChildAddr;

	TRACE_printf(("TxUnetLeaveReport: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_LEAVE_FRAME), MT_DATA_IND, UNET_LEAVE_REPORT);

}

UINT8 UNET_LEAVE(void)
{
	UNET_HEADER* TxPtr;

	TRACE_puts("UNET_LEAVE");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_LEAVE_CMD;
	TxPtr->DstAddr = UnetSys.JoinParent;
	TxPtr->SrcAddr = UnetSys.NwkAddr;
	TxPtr->MHR.DstAddr = UnetSys.JoinParent;

	TRACE_printf(("UNET_LEAVE: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_LEAVE_CMD);

}

UINT8 UNET_ADDR16_64(UINT16 DstAddr)
{
	UNET_HEADER* TxPtr;
//	UINT8 i;

	TRACE_puts("UNET_ADDR16_64");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_ASK_MAC_ADDR;
	TxPtr->DstAddr = DstAddr;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->MHR.DstAddr = 0xffff;
	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TRACE_printf(("UNET_ADDR16_64: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_ASK_MAC_ADDR);

}

UINT8 TxUnetMARsp(UINT16 DstAddr)
{
	UNET_RSP_MA_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("TxUnetMARsp");

	TxPtr = (UNET_RSP_MA_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_RSP_MA_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_RSP_MAC_ADDR;
	TxPtr->UNETHeader.DstAddr = DstAddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->UNETHeader.MHR.DstAddr = 0xffff;

	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	MSG_Copy(TxPtr->RspMACAddress, &MAC_ADDRESS, 8);

	TRACE_printf(("TxUnetMARsp: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_RSP_MA_FRAME), MT_DATA_IND, UNET_RSP_MAC_ADDR);

}
#if 0
UINT8 TxUnetCleanSpace(UINT16 parentaddr, UINT16 childaddr)
{
	UNET_LEAVE_FRAME* TxPtr;
	UINT8 i;

	TRACE_puts("TxUnetCleanSpace");

	TxPtr = (UNET_LEAVE_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_LEAVE_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_CS;
	TxPtr->UNETHeader.DstAddr = parentaddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	TxPtr->LeaveChildAddress = childaddr;

	TRACE_printf(("TxUnetCleanSpace: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_LEAVE_FRAME), MT_DATA_IND, UNET_CS);

}
#endif

#ifdef I_Am_Coordinator
UINT8 UNET_QUERY(UINT16 DstAddr)//use for poll test
{
	UNET_HEADER* TxPtr;
//	UINT8 i;

	TRACE_puts("UNET_QUERY");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_QUERY_CMD;
	TxPtr->DstAddr = DstAddr;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->MHR.DstAddr = 0xffff;
		TxPtr->MHR.Header.val = 0x8801;
	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((TxPtr->MHR.DstAddr = unet_tree_routing(TxPtr->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TRACE_printf(("UNET_QUERY: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_QUERY_CMD);

}
#endif

UINT8 TxUnetRspQueryRelay(void)
{
	UNET_QUERY_FRAME* TxPtr;

	TRACE_puts("TxUnetRspQueryRelay");

	TxPtr = (UNET_QUERY_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_QUERY_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_QUERY_RELAY;
	TxPtr->UNETHeader.DstAddr = UnetSys.JoinParent;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.MHR.DstAddr = TxPtr->UNETHeader.DstAddr;

	TxPtr->RXRSSI = RSSIValue;

	TRACE_printf(("TxUnetRspQueryRelay: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_QUERY_FRAME), MT_DATA_IND, UNET_RSP_QUERY);

}

UINT8 UNET_TX64(UINT8* DstMAC, UINT8* DataPtr, UINT8 Length)
{
	UNET_MAC_ROUTE_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("UNET_TX64");

	if(Length > UNET_MAX_TX64_DATA_PAYLOAD_LENGTH)
		return DATA_TOO_LONG;

	TxPtr = (UNET_MAC_ROUTE_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_MAC_ROUTE_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_MAC_ROUTE;
	TxPtr->UNETHeader.DstAddr = UNET_COORD_ADDRESS;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	MSG_Copy(TxPtr->DstMACAddress, DstMAC, 8);
	TxPtr->DataLength = Length;

	MSG_Copy(&RF_TX_BUFF[sizeof(UNET_MAC_ROUTE_FRAME)], DataPtr, Length);

	TRACE_printf(("UNET_TX64: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_MAC_ROUTE_FRAME) + Length, MT_DATA_IND, UNET_MAC_ROUTE);

}

UINT8 TxUnetLocalQuery(UINT16 DstAddr, UINT32 Interval, UINT8 Switch)
{
	UNET_LOCAL_QUERY_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("TxUnetLocalQuery");

	TxPtr = (UNET_LOCAL_QUERY_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_LOCAL_QUERY_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_LOCAL_QUERY;
	TxPtr->UNETHeader.DstAddr = DstAddr;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	if(DstAddr == 0xffff){
		TxPtr->UNETHeader.MHR.DstAddr = 0xffff;

	}else if(DstAddr == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TxPtr->Interval = Interval;

	TxPtr->Switch = Switch;

	if(Switch)
		poll.ETA = Interval;
	else
		poll.flag.down_poll_flg = 0;

	TRACE_printf(("TxUnetLocalQuery: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_LOCAL_QUERY_FRAME), MT_DATA_IND, UNET_LOCAL_QUERY);

}

UINT8 RxUnetLocalQuery(UNET_LOCAL_QUERY_FRAME* MsgPtr)
{
	TRACE_puts("RxUnetLocalQuery");

//set interval
	poll.ETA = MsgPtr->Interval;

	if(poll.ETA == 0x88000088){
		UnetSys.Flag.PermitJoin = 0;
		return SUCCESS;
	}
	else if(poll.ETA == 0xccffffcc)
	{
		UnetSys.Flag.PermitJoin = 1;
		return SUCCESS;
	}

//Switch polling light indication
	if(MsgPtr->Switch && !poll.flag.up_poll_flg){
#ifdef TIMER_1MS
		poll_tm = setup_timer(poll.ETA, 0, (void (*)())TxUnetLocalTalk, NULL);
#else
		poll.up_poll_counter = 0;
#endif
		poll.flag.up_poll_flg = 1;
		User_LED_On();
	}
	else if(!MsgPtr->Switch && poll.flag.up_poll_flg){
#ifdef TIMER_1MS
		close_timer(poll_tm);
#endif
		poll.flag.up_poll_flg = 0;
		User_LED_Off();
	}

	return SUCCESS;

}

UINT8 TxUnetLocalTalk(void)
{
	UNET_LOCAL_TALK_FRAME* TxPtr;

	TRACE_puts("TxUnetLocalTalk");

	TxPtr = (UNET_LOCAL_TALK_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_LOCAL_TALK_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.DstAddr = UnetSys.JoinParent;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_LOCAL_TALK;
	TxPtr->UNETHeader.DstAddr = UnetSys.JoinParent;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	memcpy(TxPtr->mac_address, MAC_ADDRESS, 8);
	TxPtr->poll_interval = poll.ETA;
#ifdef TIMER_1MS
	reset_timer(poll_tm);
#endif
	TRACE_printf(("TxUnetLocalTalk: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_LOCAL_TALK_FRAME), MT_DATA_IND, UNET_LOCAL_TALK);

}

void RxUnetLocalTalk(UNET_LOCAL_TALK_FRAME* MsgPtr)
{
	struct _child_list_ *ChiPtr;

	TRACE_puts("RxUnetLocalTalk");

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->NetworkAddress == MsgPtr->UNETHeader.MHR.SrcAddr && ChiPtr->Available){
			if(!memcmp(ChiPtr->MacAddr, MsgPtr->mac_address, 8)){//compare mac address
				ChiPtr->rx_polling_flg = 1;
#ifdef TIMER_1MS
			if(!ChiPtr->rx_polling_switch){
				ChiPtr->rx_polling_switch = 1;
				ChiPtr->tm = setup_timer(MsgPtr->poll_interval, 0, PollCheck, &ChiPtr->NetworkAddress);
			}
#else
			ChiPtr->rx_polling_switch = 1;
#endif
			}else
				unet_tx_disasso(MsgPtr->mac_address, 0x1, 0xffff);

		}
	    } while(ChiPtr != UnetSys.ChildTail);
	}

	poll.flag.down_poll_flg = 1;

}

#ifdef TIMER_1MS
void PollCheck(UINT16 *nwk_address)
{
	struct _child_list_ *ChiPtr;

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->NetworkAddress != *nwk_address)
			continue;

		if(!ChiPtr->rx_polling_switch)
			break;

		if(ChiPtr->rx_polling_flg) {
			ChiPtr->rx_polling_flg = 0;
			reset_timer(ChiPtr->tm);
			break;
		}

		if(!TxUnetLocalTalkAlert(ChiPtr->NetworkAddress)) {
			ChiPtr->rx_polling_switch = 0;
//			close_timer(ChiPtr->tm);
//			ChiPtr->tm = NULL;
		}
		else {
			reset_timer(ChiPtr->tm);
		}
		break;
	    } while(ChiPtr != UnetSys.ChildTail);
	}
}
#endif

UINT8 TxUnetLocalTalkAlert(UINT16 nwkAddress)
{
	UNET_HEADER* TxPtr;

	TRACE_puts("TxUnetLocalTalkAlert");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.DstAddr = nwkAddress;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_LOCAL_TALK_RSP;
	TxPtr->DstAddr = nwkAddress;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	TRACE_printf(("TxUnetLocalTalkAlert: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_LOCAL_TALK_RSP);

}

#ifdef I_Am_Coordinator
UINT8 RxUnetMACRouting(UNET_MAC_ROUTE_FRAME* MsgPtr)
{
	UNET_HEADER* TxPtr;
//	UINT8 i;
	UINT16 PassAddress;
#ifdef I_Am_Coordinator
	struct _unet_children_table_ *ChiPtr;
#endif

	TRACE_puts("RxUnetMACRouting");

#ifdef I_Am_Coordinator
	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(memcmp(ChiPtr->MacAddress, MsgPtr->DstMACAddress, 8) == 0){
			PassAddress = ChiPtr->NwkAddress;
			break;
		}
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}
#endif

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_DATA;
	TxPtr->DstAddr = PassAddress;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(PassAddress == 0xffff){
		TxPtr->MHR.DstAddr = 0xffff;

	}else if(PassAddress == UnetSys.NwkAddr){
		return DEST_IS_DEVSELF;
	}else{
		if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	MSG_Copy(&RF_TX_BUFF[sizeof(UNET_HEADER)], (UINT8 *)MsgPtr+sizeof(UNET_MAC_ROUTE_FRAME), MsgPtr->DataLength);

	TRACE_printf(("RxUnetMACRouting: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER) + MsgPtr->DataLength, MT_DATA_IND, UNET_DATA);

}
#endif // #ifdef I_Am_Coordinator

UINT8 RxUnetRspQueryRelay(UNET_QUERY_FRAME* RxPtr)
{
	UNET_QUERY_FRAME* TxPtr;
//	UINT8 i;

	TRACE_puts("RxUnetRspQueryRelay");

	TxPtr = (UNET_QUERY_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_QUERY_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_RSP_QUERY;
	TxPtr->UNETHeader.DstAddr = UNET_COORD_ADDRESS;
	TxPtr->UNETHeader.SrcAddr = RxPtr->UNETHeader.SrcAddr;

	TxPtr->UNETHeader.MHR.DstAddr = TxPtr->UNETHeader.DstAddr;


	TxPtr->RXRSSI = RxPtr->RXRSSI;

	TxPtr->TXRSSI = RSSIValue;

	if(UnetSys.NwkAddr == UNET_COORD_ADDRESS){
		TxPtr->UNETHeader.SrcAddr = RxPtr->UNETHeader.SrcAddr;
		return RxUnetRspQuery(TxPtr);
	}

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	TRACE_printf(("RxUnetRspQueryRelay: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_QUERY_FRAME), MT_DATA_IND, UNET_RSP_QUERY);

}

UINT8 RxUnetRspQuery(UNET_QUERY_FRAME* MsgPtr)
{
#if DEBUG_FUNC

#ifdef I_Am_Coordinator
	UINT8 Temp[8];
	struct _unet_children_table_ *ChiPtr;

	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
	    	ChiPtr = ChiPtr->Next;
			if(ChiPtr->NwkAddress == MsgPtr->UNETHeader.SrcAddr){
				if(ChiPtr->rx_rssi_query_number < 10)
					ChiPtr->rx_rssi_query_number += 1;
				else{
					Temp[0] = 0xcc;
					Temp[1] = 0x4;
					Temp[2] = UNET_RSP_QUERY;
					Temp[3] = (UINT8)((MsgPtr->UNETHeader.SrcAddr >> 8) & 0xff);
					Temp[4] = (UINT8)(MsgPtr->UNETHeader.SrcAddr & 0xff);
					Temp[5] = MsgPtr->TXRSSI;
					Temp[6] = MsgPtr->RXRSSI;
					Temp[7] = 0xdd;
					putdata(8, Temp);
					ChiPtr->rx_rssi_query_number = 0;
					return SUCCESS;

				}
			}
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}
#endif

#else

    #ifdef CONSOLE
	UINT8 Temp[8];

	TRACE_puts("RxUnetRspQuery");

	Temp[0] = 0xcc;
	Temp[1] = 0x5;// UNET_RSP_QUERY;
	Temp[2] = UNET_RSP_QUERY;// 0x4;
//	MSG_Copy(&Temp[3], &(MsgPtr->UNETHeader.SrcAddr), 2);
	Temp[3] = (UINT8)((MsgPtr->UNETHeader.SrcAddr >> 8) & 0xff);
	Temp[4] = (UINT8)(MsgPtr->UNETHeader.SrcAddr & 0xff);
	Temp[5] = MsgPtr->TXRSSI;
	Temp[6] = MsgPtr->RXRSSI;
	Temp[7] = 0xdd;
	putdata(8, Temp);
    #endif

#endif // #if DEBUG_FUNC
	return SUCCESS;
}

UINT8 RxUnetRspMA(UNET_RSP_MA_FRAME* MsgPtr)
{
#ifdef CONSOLE
	UINT8 Temp[13];
	UINT8 swap[8];

	TRACE_puts("RxUnetRspMA");

	MSG_Copy(swap, MsgPtr->RspMACAddress, 8);

	Temp[0] = 0xcc;
	Temp[1] = 0xb;
	Temp[2] = UNET_RSP_MAC_ADDR;

	Temp[3] = swap[7];
	Temp[4] = swap[6];
	Temp[5] = swap[5];
	Temp[6] = swap[4];
	Temp[7] = swap[3];
	Temp[8] = swap[2];
	Temp[9] = swap[1];
	Temp[10] = swap[0];

//	MSG_Copy(&Temp[3], MsgPtr->RspMACAddress, 8);
//	MSG_Copy(&Temp[10], &(MsgPtr->UNETHeader.SrcAddr), 2);
	Temp[11] = (UINT8)((MsgPtr->UNETHeader.SrcAddr >> 8) & 0xff);
	Temp[12] = (UINT8)(MsgPtr->UNETHeader.SrcAddr & 0xff);
	putdata(13, Temp);
#endif

	return SUCCESS;
}

void RxUnetData(UNET_HEADER* RxPtr, UINT8 Length)
{
#ifdef DATAOUT
//	UINT8 dataBuffer[128];
	UINT8 dataLength;
#endif


#ifdef I_Am_Coordinator
//	UINT8 Temp[5];
#endif

#ifdef CHECKSUM
	UINT8 DataLength, Checksum;
	BOOL check_sum_status;
#endif

	TRACE_puts("RxUnetData");

#ifdef I_Am_Coordinator
#ifdef CHECKSUM
	ReceivedNumber+=1;
//	memcpy(Temp, &ReceivedNumber, 4);
	DataLength = ((UINT8*)RxPtr)[18];
	Checksum = ((UINT8*)RxPtr)[19];

	check_sum_status = UnetCheckSumCertification(((UINT8 *) RxPtr + sizeof(UNET_HEADER)) + 2, DataLength, Checksum);

//	putdata(4, Temp);
#ifdef CONSOLE
	printf("Num = %Lx\r\n", ReceivedNumber);
#endif

	if(check_sum_status == 0){
		Temp[0] = 0xcc;
		Temp[1] = UNET_DATA;
		Temp[2] = 0xff;
		putdata(3, Temp);
#ifdef CONSOLE
		printf("ERROR OCCURED\r\n");
#endif
		while(1){

		}
	}
#endif // #ifdef CHECKSUM

//	Temp[0] = 0xcc;
//	Temp[1] = UNET_DATA;
//	Temp[2] = 0x00;
//	putdata(3, Temp);

#endif // #ifdef I_Am_Coordinator


#ifdef DATAOUT
	dataLength = ((UINT8*)RxPtr)[sizeof(UNET_HEADER)];

 #if 1	// 2007/7/4 15:10, Sunny: remove 128 bytes output buffer request.
	putchar(0xcc);
	putchar(dataLength + 4);
	putchar(UNET_RX_DATA);
//	memcpy(dataBuffer+3, &RxPtr->SrcAddr.ShortAddr, 2);
	putchar((RxPtr->SrcAddr >> 8) & 0xff);
	putchar(RxPtr->SrcAddr & 0xff);
	putchar(dataLength);
	putdata(dataLength, (UINT8 *)RxPtr + sizeof(UNET_HEADER) + 1);
 #else
	dataBuffer[0] = 0xcc;
	dataBuffer[1] = dataLength + 4;
	dataBuffer[2] = UNET_RX_DATA;
	memcpy(dataBuffer+3, &RxPtr->SrcAddr, 2);
	dataBuffer[5] = dataLength;
	memcpy(dataBuffer+6, (((UINT8 *) RxPtr + sizeof(UNET_HEADER)) + 1), dataLength);
    #ifdef CONSOLE
	putdata(dataLength+6, dataBuffer);
    #endif
 #endif

#endif // #ifdef DATAOUT
}

void RxUnetReset(void)
{
	struct _child_list_ *ChiPtr;

	TRACE_puts("RxUnetReset");

	UnetSys.Flag.PermitJoin = 0;//Turn off permit join

	if(UnetSys.Flag.Endev || (UnetSys.JoinEndevCnt+UnetSys.JoinRouterCnt) == 0) {
		TRACE_TAG();
		UnetSys.Flag.NwkReset = 1;
		return;
	}

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do { //disassociate all of my children
		ChiPtr = ChiPtr->Next;
		unet_tx_disasso(ChiPtr->MacAddr, 0x1, 0xffff);
	    } while(ChiPtr != UnetSys.ChildTail);
	}

	TRACE_TAG();
	UnetSys.Flag.NwkReset = 1;
}

#ifdef I_Am_Coordinator
UINT8 RxUnetJoinReport(UNET_JOINREPORT_FRAME* MsgPtr)
{
//	UINT8 *TmPtr;
	struct _unet_children_table_ *ChiPtr;

	TRACE_puts("RxUnetJoinReport");

//	TmPtr = (UINT8 *) MsgPtr;

	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(memcmp(ChiPtr->MacAddress, MsgPtr->JoinChildMACAddress, 8) == 0){
			if(ChiPtr->NwkAddress == MsgPtr->JoinChildNWKAddress){
				return CHILD_IN_TABLE;
			}
#if 0
			TxUnetCleanSpace(ChiPtr->ParentAddress, ChiPtr->NwkAddress);
#endif
			ChiPtr->NwkAddress = MsgPtr->JoinChildNWKAddress;
			ChiPtr->ParentAddress = MsgPtr->UNETHeader.SrcAddr;
			goto RX_UNET_JOIN_REPORT_LABEL;
		}
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}

	if(insert_node((void *)&UnetSys.ChildTableTail, sizeof( struct _unet_children_table_)) == NULL)
		return FAILURE;

	UnetSys.ChildTableTail->NwkAddress = MsgPtr->JoinChildNWKAddress;
	UnetSys.ChildTableTail->ParentAddress = MsgPtr->UNETHeader.SrcAddr;

	MSG_Copy(UnetSys.ChildTableTail->MacAddress, MsgPtr->JoinChildMACAddress, 8);

RX_UNET_JOIN_REPORT_LABEL:

//	UNET_GET_TABLE();
	reset_timer(gettable_tm);

	return SUCCESS;
}
#endif

UINT8 RxUnetKick(UNET_KICK_FRAME* MsgPtr)
{
	struct _child_list_ *ChiPtr;

	TRACE_puts("RxUnetKick");

	UnetSys.Flag.PermitJoin = 0;

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->NetworkAddress == MsgPtr->KickChildAddress) {
			delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);

			RecycleAddress[RecycleIndex] = MsgPtr->KickChildAddress;
			RecycleIndex+=1;

			AddrRecycleFlg = 1;
			if(ChiPtr->Cap & 0x02)	// Router
				UnetSys.JoinRouterCnt--;
			else	// End device
				UnetSys.JoinEndevCnt--;
			unet_tx_disasso(ChiPtr->MacAddr, 0x1, MsgPtr->NewParent);

			goto RX_UNET_KICK_LABEL;
		}
	    } while(ChiPtr != UnetSys.ChildTail);
	}

//	WaitMS(100 + rand() % 400);
	UnetSys.Flag.PermitJoin = 1;
	return DISCARD_FRAME;//No children match

RX_UNET_KICK_LABEL:
	UnetSys.Flag.PermitJoin = 1;
	return SUCCESS;

}
#ifdef I_Am_Coordinator
UINT8 RxUnetLeaveReport(UNET_LEAVE_FRAME* MsgPtr)//coordinator receive the device leave report
{
	struct _unet_children_table_ *ChiTabPtr;

	TRACE_puts("RxUnetLeaveReport");

	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    do { //clean the children table
		ChiTabPtr = ChiTabPtr->Next;
		if(ChiTabPtr->NwkAddress == MsgPtr->LeaveChildAddress) {
			clean_branch(MsgPtr->LeaveChildAddress, MsgPtr->UNETHeader.SrcAddr);
			delete_node((void *)&UnetSys.ChildTableTail, (void *)&ChiTabPtr);
			break;
		}
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}

	//UNET_GET_TABLE();
	reset_timer(gettable_tm);

	return SUCCESS;
}
#endif

UINT8 RxUnetLeave(UNET_HEADER* MsgPtr)//router receive the child want to leave
{

	struct _child_list_ *ChiPtr;

#ifdef I_Am_Coordinator
	struct _unet_children_table_ *ChiTabPtr;
#endif

	TRACE_puts("RxUnetLeave");

#ifdef I_Am_Coordinator
	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    do { //clean the children table
		ChiTabPtr = ChiTabPtr->Next;
		if(ChiTabPtr->NwkAddress == MsgPtr->SrcAddr) {
			delete_node((void *)&UnetSys.ChildTableTail, (void *)&ChiTabPtr);
			break;
		}
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}
	//UNET_GET_TABLE();
	reset_timer(gettable_tm);
#endif

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->NetworkAddress == MsgPtr->SrcAddr) {
			delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);
			goto RX_UNET_LEAVE_LABEL;
		}
	    } while(ChiPtr != UnetSys.ChildTail);
	}

	return DISCARD_FRAME;

RX_UNET_LEAVE_LABEL:
	TxUnetLeaveReport(MsgPtr->SrcAddr);
	return SUCCESS;
}
#if 0
UINT8 RxUnetCleanSpace(UNET_LEAVE_FRAME* MsgPtr)
{
	struct _child_list_ *ChiPtr;

	TRACE_puts("RxUnetCleanSpace");

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->NetworkAddress == MsgPtr->LeaveChildAddress) {
			delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);
	 		goto RX_UNET_CLEAN_SPACE_LABEL;
		}
	    } while(ChiPtr != UnetSys.ChildTail);
	}
	return FAILURE;

RX_UNET_CLEAN_SPACE_LABEL:
	return SUCCESS;
}
#endif
void NetworkReset(void)
{
	TRACE_puts("NetworkReset");

	if(UnetSys.Flag.AutoChannel)
		UnetSys.Channel = 0xff;

	if(UnetSys.Flag.AutoPID)
		UnetSys.JoinPID = 0xffff;

	UNET_INIT(UnetSys.JoinPID, UnetSys.Channel, UnetSys.RejoinParent,
		  UnetSys.MaxChild, UnetSys.MaxRouter, UnetSys.MaxDepth);
//	UnetSys.Flag.NwkReady = 0;
//	RSTSRC |= 0x10;
//	SystemReset();
}

#ifdef I_Am_Coordinator
void UNET_GET_TABLE(void)
{
	struct _unet_children_table_ *ChiPtr;
	UINT8 j;

	TRACE_puts("UNET_GET_TABLE");

	putchar(0xcc);	//header
	j = 0;
	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		j++;
		ChiPtr = ChiPtr->Next;
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}
	putchar(j);
	putchar(UNET_RSP_ROUTERTAB);

	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		for(j = 8; j--; )
			putchar(ChiPtr->MacAddress[j]);

		putchar((ChiPtr->NwkAddress >> 8) & 0xff);
		putchar(ChiPtr->NwkAddress & 0xff);

		putchar((ChiPtr->ParentAddress >> 8) & 0xff);
		putchar(ChiPtr->ParentAddress & 0xff);
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}

	putchar(0xdd);	//tail
}

UINT8 TxUnetReqTable(UINT16 dst_nwk_address)
{
	struct _unet_children_table_ *ChiTabPtr;
	struct _child_list_ *ChiPtr;
	UNET_HEADER* TxPtr;
	UINT8 i;
	UINT8 exist_flag;

	TRACE_puts("TxUnetReqTable");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	TxPtr->MHR.Header.val = 0x8821;
	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_REQ_TAB;
	TxPtr->DstAddr = dst_nwk_address;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(dst_nwk_address == 0xffff){
		TxPtr->MHR.DstAddr = 0xffff;
		TxPtr->MHR.Header.val = 0x8801;
	}else if(dst_nwk_address == UnetSys.NwkAddr){

		if((ChiPtr = UnetSys.ChildTail) != NULL) {
			for(i=0;i<(UnetSys.JoinEndevCnt+UnetSys.JoinRouterCnt);i++){
				exist_flag = 1;

				ChiPtr = ChiPtr->Next;
				if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    			do {
						ChiTabPtr = ChiTabPtr->Next;

						if(memcmp(ChiTabPtr->MacAddress, ChiPtr->MacAddr, 8) == 0 /* && (MsgPtr->chi_tab[i].nwk_address == ChiTabPtr->NwkAddress) && (MsgPtr->UNETHeader.SrcAddr == ChiTabPtr->ParentAddress)*/){
							exist_flag = 0;
						}

	    			} while(ChiTabPtr != UnetSys.ChildTableTail);

				}

				if(exist_flag){
					if(insert_node((void *)&UnetSys.ChildTableTail, sizeof( struct _unet_children_table_)) == NULL)
						return FAILURE;

					UnetSys.ChildTableTail->NwkAddress = ChiPtr->NetworkAddress;
					UnetSys.ChildTableTail->ParentAddress = UnetSys.NwkAddr;

					MSG_Copy(UnetSys.ChildTableTail->MacAddress, ChiPtr->MacAddr, 8);
					//exist_flag = 0;
					//UNET_GET_TABLE();
					reset_timer(gettable_tm);
				}

			}

		}




			return DEST_IS_DEVSELF;

	}else{
		if((TxPtr->MHR.DstAddr = unet_tree_routing(TxPtr->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	TRACE_printf(("TxUnetReqTable: DstAddr=%04X, SrcAddr=%04X", TxPtr->DstAddr, TxPtr->SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_REQ_TAB);

}

UINT8 RxUnetRspTable(UNET_TAB_FRAME* MsgPtr)
{
	struct _unet_children_table_ *ChiTabPtr;
	UINT8 i, exist_flag;

	TRACE_puts("RxUnetRspTable");

	for(i=0;i<MsgPtr->chi_cnt;i++){
		exist_flag = 1;
		SWAPINT16(&(MsgPtr->chi_tab[i].nwk_address));
		if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
		    do {
			ChiTabPtr = ChiTabPtr->Next;

			//if the child had been in the child table, do not add.
			if(!memcmp(ChiTabPtr->MacAddress, MsgPtr->chi_tab[i].mac_address, 8)/* && (MsgPtr->chi_tab[i].nwk_address == ChiTabPtr->NwkAddress) && (MsgPtr->UNETHeader.SrcAddr == ChiTabPtr->ParentAddress)*/){
				exist_flag = 0;
				if((MsgPtr->chi_tab[i].nwk_address == ChiTabPtr->NwkAddress) && (MsgPtr->UNETHeader.SrcAddr == ChiTabPtr->ParentAddress))
					break;
				else{
#if 0
					TxUnetCleanSpace(ChiTabPtr->ParentAddress, ChiTabPtr->NwkAddress);
#endif
					ChiTabPtr->NwkAddress = MsgPtr->chi_tab[i].nwk_address;
					ChiTabPtr->ParentAddress = MsgPtr->UNETHeader.SrcAddr;
					reset_timer(gettable_tm);
				}
			}
		    } while(ChiTabPtr != UnetSys.ChildTableTail);
		}

		if(exist_flag){
			if(insert_node((void *)&UnetSys.ChildTableTail, sizeof( struct _unet_children_table_)) == NULL)
				return FAILURE;

			UnetSys.ChildTableTail->NwkAddress = MsgPtr->chi_tab[i].nwk_address;
			UnetSys.ChildTableTail->ParentAddress = MsgPtr->UNETHeader.SrcAddr;

			MSG_Copy(UnetSys.ChildTableTail->MacAddress, MsgPtr->chi_tab[i].mac_address, 8);

			//UNET_GET_TABLE();
			reset_timer(gettable_tm);
		}
	}

	return SUCCESS;
}


#endif

void UNET_GET_INFOMATION(void)
{
	UINT8 i;
    putchar(0xcc);//header
    putchar(strlen(UNET01_VERSION) + 17);//length
    putchar(UNET_GET_INFO);//command type
    putchar(UnetSys.MaxChild);
    putchar(UnetSys.MaxRouter);
    putchar(UnetSys.MaxDepth);

    putchar(UnetSys.Channel);
    putchar(UnetSys.JoinPID >> 8);
    putchar(UnetSys.JoinPID & 0xff);

    for(i = 8; i--; )
        putchar(MAC_ADDRESS[i]);

    putchar(UnetSys.NwkAddr >> 8);
    putchar(UnetSys.NwkAddr & 0xff);

    puts(UNET01_VERSION);
    putchar(0xdd);//tail

}

UINT8 RxUnetReqTable(void)
{
	struct _child_list_ *ChiPtr;
	UNET_TAB_FRAME* TxPtr;
//	UINT8 i
	UINT8 j, k;

	TRACE_puts("RxUnetReqTable");

	TxPtr = (UNET_TAB_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_TAB_FRAME));

	//program the MAC frame control
	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_RSP_TAB;
	TxPtr->UNETHeader.DstAddr = UNET_COORD_ADDRESS;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	j = 0;
	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		j++;
		ChiPtr = ChiPtr->Next;
	    } while(ChiPtr != UnetSys.ChildTail);
	}
	else
		return 0;



	TxPtr->chi_cnt = j;

	k = 0;
	if((ChiPtr = UnetSys.ChildTail) != NULL) {
    	do {
			ChiPtr = ChiPtr->Next;

			MSG_Copy(TxPtr->chi_tab[k].mac_address, ChiPtr->MacAddr, 8);
			TxPtr->chi_tab[k].nwk_address = ChiPtr->NetworkAddress;
			SWAPINT16(&(TxPtr->chi_tab[k].nwk_address));
			k+=1;

		} while(ChiPtr != UnetSys.ChildTail);
	}

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	TRACE_printf(("RxUnetReqTable: DstAddr=%04X, SrcAddr=%04X", TxPtr->UNETHeader.DstAddr, TxPtr->UNETHeader.SrcAddr));
	return UzTx(RF_TX_BUFF, sizeof(UNET_TAB_FRAME), MT_DATA_IND, UNET_RSP_TAB);

}

void UnetRecovery(UINT16 failure_address)
{
	struct _child_list_ *ChiPtr;
#ifdef I_Am_Coordinator
	struct _unet_children_table_ *ChiTabPtr;
#endif

	TRACE_puts("UnetRecovery");

	if(UnetSys.Flag.PanCoordinator){
#ifdef I_Am_Coordinator
		if((ChiPtr = UnetSys.ChildTail) != NULL) {
		    do { //clean the coordinator child list
			ChiPtr = ChiPtr->Next;
			if(/*(ChiPtr->NetworkAddress == failure_address) && */ChiPtr->tx_failure) {
				ChiPtr->Available = 0;
				ChiPtr->tx_failure = 0;
				ChiPtr->rx_polling_switch = 0;
				ChiPtr->rx_polling_flg = 0;
				if(ChiPtr->Cap & 0x02)	// Router
					UnetSys.JoinRouterCnt--;
				else	// End device
					UnetSys.JoinEndevCnt--;

				close_timer(ChiPtr->tm);
				ChiPtr->tm = NULL;
				RecycleAddress[RecycleIndex] = ChiPtr->NetworkAddress;
				RecycleIndex+=1;
				AddrRecycleFlg = 1;
				delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);
				break;
			}
		    } while(ChiPtr != UnetSys.ChildTail);
		}

		if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
		    do { //clean the failure network address and related possible table
			ChiTabPtr = ChiTabPtr->Next;
			if(ChiTabPtr->NwkAddress == failure_address) {
				clean_branch(failure_address, UnetSys.NwkAddr);
				delete_node((void *)&UnetSys.ChildTableTail, (void *)&ChiTabPtr);
				break;
			}
		    } while(ChiTabPtr != UnetSys.ChildTableTail);
		}

		//UNET_GET_TABLE();
		reset_timer(gettable_tm);
#endif
	}
	else{
		if(failure_address == UnetSys.JoinParent)//send to upper layer failure
			RxUnetReset();
		else{//send to lower layer
			//clean the router child list
			if((ChiPtr = UnetSys.ChildTail) != NULL) {
			    do {
				ChiPtr = ChiPtr->Next;
				if(ChiPtr->NetworkAddress == failure_address) {
					close_timer(ChiPtr->tm);
					ChiPtr->tm = NULL;
					delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);
					break;
				}
			    } while(ChiPtr != UnetSys.ChildTail);
			}
			TxUnetLeaveReport(failure_address);
			RecycleAddress[RecycleIndex] = failure_address;
			RecycleIndex+=1;
			AddrRecycleFlg = 1;
			if(ChiPtr->Cap & 0x02)	// Router
				UnetSys.JoinRouterCnt--;
			else	// End device
				UnetSys.JoinEndevCnt--;
		}
	}
}

void UnetChildAliveCheck(void)
{
#ifdef I_Am_Coordinator
	struct _unet_children_table_ *ChiTabPtr;
	UINT8 flag = 0;
	UINT16 addr;
#endif
	struct _child_list_ *ChiPtr;

	TRACE_puts("UnetChildAliveCheck");

	TRACE_printf(("RecycleIndex = %02X", RecycleIndex));
	TRACE_printf(("RecycleAddr=%04X,%04X,%04X,%04X,%04X", RecycleAddress[0], RecycleAddress[1], RecycleAddress[2], RecycleAddress[3],RecycleAddress[4]));

//	if(!UnetSys.Flag.TxFailure){
//		reset_timer(chdalive_tm);
//		return;
//	}

	if((ChiPtr = UnetSys.ChildTail) != NULL) {
	    do {
		ChiPtr = ChiPtr->Next;
		if(ChiPtr->tx_failure){
			ChiPtr->Available = 0;
			if(ChiPtr->Cap & 0x02)	// Router
				UnetSys.JoinRouterCnt--;
			else	// End device
				UnetSys.JoinEndevCnt--;

			ChiPtr->Available = 0;
			ChiPtr->tx_failure = 0;
			ChiPtr->rx_polling_switch = 0;
			ChiPtr->rx_polling_flg = 0;

		#ifdef I_Am_Coordinator
			addr =
		#endif
			RecycleAddress[RecycleIndex] = ChiPtr->NetworkAddress;

		#ifdef I_Am_Coordinator
			TRACE_printf(("Dead Address: %04X", addr));
			flag = 1;
		#endif

			RecycleIndex+=1;
			AddrRecycleFlg = 1;
			close_timer(ChiPtr->tm);
			ChiPtr->tm = NULL;
			delete_node((void *)&UnetSys.ChildTail, (void *)&ChiPtr);
			break;
		}
	    } while(ChiPtr != UnetSys.ChildTail);
	}

#ifdef I_Am_Coordinator
	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL && flag) {
	    do {
		ChiTabPtr = ChiTabPtr->Next;
		if(ChiTabPtr->NwkAddress == addr){
			clean_branch(addr, UnetSys.NwkAddr);
			delete_node((void *)&UnetSys.ChildTableTail, (void *)&ChiTabPtr);
			break;
		}
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}
#endif

	reset_timer(chdalive_tm);
}

#ifdef I_Am_Coordinator
UINT8 UnetTxCheck(UINT16 dstaddr)
{
	struct _unet_children_table_ *ChiTabPtr;

	if(dstaddr == UNET_COORD_ADDRESS)
		return 0;

	if(dstaddr == 0xffff)
		return 1;

	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		ChiTabPtr = ChiTabPtr->Next;
		if(ChiTabPtr->NwkAddress == dstaddr)
			return 1;
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}

	return 0;
}
#endif

#if DEBUG_FUNC

#ifdef I_Am_Coordinator
void dbg_rssi_query(void)
{
	struct _unet_children_table_ *ChiPtr;

	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
	    	ChiPtr = ChiPtr->Next;
			UNET_QUERY(ChiPtr->NwkAddress);
			WaitMS(50);
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}
	reset_timer(rssi_dbg_tm);
}
#endif

uint8 dbg_tx_node_info_req(uint16 dst_addr)
{
	UNET_HEADER* TxPtr;
	uint8 i;
	TRACE_puts("dbg_tx_node_info_req");

	TxPtr = (UNET_HEADER *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_HEADER));

	//program the MAC frame control
	if(dst_addr != 0xffff)
		TxPtr->MHR.Header.val = 0x8821;
	else
		TxPtr->MHR.Header.val = 0x8801;

	TxPtr->MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->MHR.DstPID = UnetSys.JoinPID;
	TxPtr->MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->MHR.DstAddr = dst_addr;
	TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UnetFrmType = UNET_DBG_NODE_INFO_REQ;
	TxPtr->DstAddr = dst_addr;
	TxPtr->SrcAddr = UnetSys.NwkAddr;

	if(dst_addr != 0xffff){
		if(dst_addr == UnetSys.NwkAddr)
			return DEST_IS_DEVSELF;
		if((TxPtr->MHR.DstAddr = unet_tree_routing(TxPtr->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
			return TREE_ROUTING_FAILED;
	}

	return UzTx(RF_TX_BUFF, sizeof(UNET_HEADER), MT_DATA_IND, UNET_DBG_NODE_INFO_REQ);
}

uint8 dbg_rx_node_info_req(void)
{
	return dbg_tx_node_info_rsp();
}

uint8 dbg_tx_node_info_rsp(void)
{
	UNET_NODE_INFO_FRAME* TxPtr;
	uint8 i;
	TRACE_puts("dbg_tx_node_info_rsp");

	TxPtr = (UNET_NODE_INFO_FRAME *) RF_TX_BUFF;
	memset(RF_TX_BUFF, 0, sizeof(UNET_NODE_INFO_FRAME));

	TxPtr->UNETHeader.MHR.Header.val = 0x8821;
	TxPtr->UNETHeader.MHR.Seqnum = UnetSys.MacDSN;
	UnetSys.MacDSN++;
	TxPtr->UNETHeader.MHR.DstPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.SrcPID = UnetSys.JoinPID;
	TxPtr->UNETHeader.MHR.DstAddr = UnetSys.JoinParent;
	TxPtr->UNETHeader.MHR.SrcAddr = UnetSys.NwkAddr;

	TxPtr->UNETHeader.Radius = UnetSys.MaxDepth*2;

	//program the UNET frame control
	TxPtr->UNETHeader.UnetSeqNum = UnetSys.NwkDSN;
	UnetSys.NwkDSN++;
	TxPtr->UNETHeader.UnetFrmType = UNET_DBG_NODE_INFO_RSP;
	TxPtr->UNETHeader.DstAddr = UNET_COORD_ADDRESS;
	TxPtr->UNETHeader.SrcAddr = UnetSys.NwkAddr;

	MSG_Copy(TxPtr->mac_address, MAC_ADDRESS, 8);
	TxPtr->my_nwk_address = UnetSys.NwkAddr;
	TxPtr->parent_nwk_address = UnetSys.JoinParent;

	if((((UNET_HEADER*)TxPtr)->MHR.DstAddr = unet_tree_routing(((UNET_HEADER*)TxPtr)->DstAddr)) == (UINT16)(-1))  //Check the destination if allready link to devself by self-healing
		return TREE_ROUTING_FAILED;

	return UzTx(RF_TX_BUFF, sizeof(UNET_NODE_INFO_FRAME), MT_DATA_IND, UNET_DBG_NODE_INFO_RSP);

}

#ifdef I_Am_Coordinator
uint8 dbg_rx_node_info_rsp(UNET_NODE_INFO_FRAME* MsgPtr)
{

	struct _unet_children_table_ *ChiTabPtr;
	uint8 exist_flag;

	exist_flag = 1;
	if((ChiTabPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
			ChiTabPtr = ChiTabPtr->Next;

			//if the child had been in the child table, do not add.
			if(!memcmp(ChiTabPtr->MacAddress, MsgPtr->mac_address, 8)){
				exist_flag = 0;
				if((MsgPtr->my_nwk_address == ChiTabPtr->NwkAddress) && MsgPtr->parent_nwk_address == ChiTabPtr->ParentAddress)
					break;
				else{
#if 0
					TxUnetCleanSpace(ChiTabPtr->ParentAddress, ChiTabPtr->NwkAddress);
#endif
					ChiTabPtr->NwkAddress = MsgPtr->my_nwk_address;
					ChiTabPtr->ParentAddress = MsgPtr->parent_nwk_address;
					reset_timer(gettable_tm);
				}
			}
	    } while(ChiTabPtr != UnetSys.ChildTableTail);
	}

	if(exist_flag){
		if(insert_node((void *)&UnetSys.ChildTableTail, sizeof( struct _unet_children_table_)) == NULL)
			return FAILURE;

		UnetSys.ChildTableTail->NwkAddress = MsgPtr->my_nwk_address;
		UnetSys.ChildTableTail->ParentAddress = MsgPtr->parent_nwk_address;
		MSG_Copy(UnetSys.ChildTableTail->MacAddress, MsgPtr->mac_address, 8);
		reset_timer(gettable_tm);
	}

	return SUCCESS;
}

void dbg_child_number_set(uint8 child_number, uint8 isMonitor)
{
	dbg_child_number = child_number;

	if(isMonitor == 1){
		if(!dbg_child_number_flag){
			dbg_child_number_flag = 1;
			child_number_dbg_tm	= setup_timer(30000, 0, dbg_child_monitor, NULL);
		}
	}
	else if(isMonitor == 0){
		if(dbg_child_number_flag){
			dbg_child_number_flag = 0;
			close_timer(child_number_dbg_tm);
		}
	}
}

void dbg_child_monitor(void)
{
	struct _unet_children_table_ *ChiPtr;
	uint8 j;

	j = 0;
	if((ChiPtr = UnetSys.ChildTableTail) != NULL) {
	    do {
		j++;
		ChiPtr = ChiPtr->Next;
	    } while(ChiPtr != UnetSys.ChildTableTail);
	}

	if(j != dbg_child_number){
		dbg_tx_node_info_req(0xffff);
		reset_timer(gettable_tm);
	}

	reset_timer(child_number_dbg_tm);
}

#endif // #ifdef I_Am_Coordinator

#endif // #ifdef DEBUG_FUNC

#ifdef CHECKSUM
UINT8 UnetCheckSum(UINT8* DataPtr, UINT8 Length)
{
	UINT8 i, CS = 0;

	TRACE_puts("UnetCheckSum");

	for(i=0;i<Length;i++)
		CS+= DataPtr[i];

	return CS;
}

BOOL UnetCheckSumCertification(UINT8* DataPtr, UINT8 Length, UINT8 CSM)
{
	UINT8 i, CS = 0;

	TRACE_puts("UnetCheckSumCertification");

	for(i=0;i<Length;i++)
		CS+= DataPtr[i];

	if(CS == CSM)
		return 1;
	else
		return 0;
}
#endif
